package com.blog.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.blog.constant.MsgConstant;
import com.blog.constant.RedisConstant;
import com.blog.pojo.dto.UserDTO;
import com.blog.pojo.dto.UserLoginDto;
import com.blog.pojo.entity.PageBean;
import com.blog.pojo.entity.User;
import com.blog.pojo.vo.UserLoginVO;
import com.blog.properties.JwtProperties;
import com.blog.result.Result;
import com.blog.service.UserService;
import com.blog.util.JwtUtil;
import com.blog.util.ThreadLocalUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RequestMapping("user")
@Slf4j
//@Controller
@RestController
@Api(tags = "用户接口")
public class UserController {


    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 注册
     * @param username
     * @param password
     * @return
     */
    @PostMapping("register")
    public Result register(String username, String password){
        log.info("开始注册：{}、{}",username,password);

        //先查询数据库中是否有该用户名的数据
        if(userService.getByUsername(username) != null){
            return Result.error(MsgConstant.USERNAME_ALREADY_EXISTS);
        }

        //行到这边，说明可以注册
        userService.register(username,password);

        return Result.success();
    }

    /**
     * 登入
     * @param userLoginDto
     * @return
     */
    @PostMapping("/login")
    public Result<UserLoginVO> userLogin(@RequestBody UserLoginDto userLoginDto){
        log.info("开始校验登入：{}" , userLoginDto);
        
        User user = userService.login(userLoginDto);
        if (user == null) {
            log.info("错误信息 {}", MsgConstant.LOGIN_FAILED);
            return Result.error(MsgConstant.LOGIN_FAILED);
        }
        
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", user.getId());
        claims.put("username", user.getUsername());
        claims.put("role", JwtProperties.ROLE_USER);

        String token = JwtUtil.createJWT(JwtProperties.secretKey, JwtProperties.time, claims);

        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set(RedisConstant.USER_TOKEN_KEY, token, 2, TimeUnit.HOURS);

        // 构建LoginVO对象
        UserLoginVO loginVO = UserLoginVO.builder()
            .token(token)
            .id(user.getId())
            .username(user.getUsername())
            .nickname(user.getNickname())
            .email(user.getEmail())
            .phone(user.getPhone())
            .avatar(user.getUserAvatar())
            .build();

        return Result.success(loginVO);
    }

    /**
     * 根据用户名查询用户信息
     * @return
     */
    @GetMapping("info")
    public Result<User> getUserByName(){
        //因为登入的用户名是唯一的，所有使用 username查询用户的信息，id和username在每次发起请求时进行拦截校验的时候存储在TreadLocal中
        Map<String, Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
//        String username = (String) map.get("username"); 旧使用方法
        //查询
        User user = userService.getByUsername(username);

        return Result.success(user);
    }

    /**
     * 分页查询用户信息
     * @param pageNum
     * @param pageSize
     * @param id
     * @param username
     * @return
     */
    @GetMapping("page")
    public Result<PageBean> getUserPage(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) Long id,
            @RequestParam(required = false) String username,
            @RequestParam(required = false) Long status)
    {
        log.info("开始分页查询用户信息:{}, {}, {}, {}, {}",pageNum, pageSize, id, username, status);

        try {
            IPage<User> page = userService.getUserPage(pageNum, pageSize, id, username, status);
            return Result.success(new PageBean<>(page.getTotal(), page.getRecords()));
        } catch (Exception e) {
            log.info("用户分页查询失败：{}", e);
            return Result.error(MsgConstant.USER_SELECT_ERROR);
        }
    }

    /**
     * 删除单个用户
     * @param id
     * @return
     */
    @DeleteMapping("delete/{id}")
    public Result deleteUser(@PathVariable Long id){
        log.info("开始单独删除用户:{}", id);

        try {
            userService.deleteUser(id);
            return Result.success(MsgConstant.SUCCESS_MSG);
        } catch (Exception e) {
            log.info("删除用户失败：{}", e);
            return Result.error(MsgConstant.USER_DELETE_ERROR);
        }
    }

    /**
     * 批量删除用户
     * @param ids
     * @return
     */
    @DeleteMapping("/deleteBatch")
    public Result deleteUsers(@RequestBody List<Long> ids){
        log.info("开始批量删除用户");

        try {
            userService.deleteUsers(ids);
            return Result.success(MsgConstant.SUCCESS_MSG);
        } catch (Exception e) {
            log.info("批量删除用户失败：{}", e);
            return Result.error(MsgConstant.USER_DELETE_ERROR);
        }
    }

    /**
     * 修改用户信息
     * @param userDTO
     * @return
     */
    @PutMapping("info")
    public Result updateUserInfo(@RequestBody UserDTO userDTO){
        log.info("开始修改用户信息：{}", userDTO);

        try {
            userService.updateUserInfo(userDTO);
            return Result.success(MsgConstant.SUCCESS_MSG);
        } catch (Exception e) {
            log.info("修改用户失败：{}",e);
            return Result.error(MsgConstant.USER_UPDATE_ERROR);
        }
    }

    /**
     *  修改密码
     * @param Pwd 前端将修改密码的表单中输入的旧密码和新密码封装成一个对象传来，需要验证旧密码是否正确
     * @return
     */
    @PutMapping("updatePwd")
    public Result updatePwd(@RequestBody Map<String, String> Pwd){
        //获取旧密码和新密码
        String oldPwd = Pwd.get("old_pwd");
        String newPwd = Pwd.get("new_pwd");

        //验证旧密码是否正确
        Map<String, Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        String userPassword = userService.getByUsername(username).getPassword();

        if( !DigestUtils.md5DigestAsHex(oldPwd.getBytes()).equals(userPassword) ){
            //旧密码不一致
            return Result.error("原密码错误");
        }

        try {
            //进行密码修改
            userService.updatePwd(newPwd);
            //删除原token
            ValueOperations valueOperations = redisTemplate.opsForValue();
            valueOperations.getOperations().delete("user-token");
            return Result.success();
        }catch (Exception e){
            return Result.error("异常");
        }
    }

    /**
     * 更新用户的头像
     * @param avatarUrl
     * @return
     */
    @PatchMapping("updateAvatar")
    public Result updateAvatar(@RequestParam String avatarUrl){
        log.info("开始修改用户头像：{}", avatarUrl);
        try{
            //将头像的url地址存入数据库
            userService.updateAvatar(avatarUrl);
            return Result.success();
        } catch (Exception e) {
            log.error("更新头像失败：", e);
            return Result.error("更新头像失败");
        }
    }

    /**
     * 获取用户数量
     * @return
     */
    @GetMapping("/count")
    public Result<Long> getUserCount(){
        log.info("开始获取用户数量");

        try {
            Long count = userService.getUserCount();
            return Result.success(count);
        } catch (Exception e) {
            log.error("获取用户数量失败：", e);
            return Result.error(MsgConstant.USER_SELECT_ERROR);
        }
    }

}
